package cn.edu.scau.cmi.ema.controller.rest;

import org.springframework.stereotype.Controller;

import java.util.List;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.io.IOException;

import com.google.gson.Gson;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;


import cn.edu.scau.cmi.ema.base.CmiPagination;
import cn.edu.scau.cmi.ema.service.base.CmiPsonService;
import cn.edu.scau.cmi.ema.base.CmiEmaController;
import cn.edu.scau.cmi.ema.dao.*;
import cn.edu.scau.cmi.ema.domain.*;
import cn.edu.scau.cmi.ema.service.*;

import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.WebDataBinder;

@Controller("UserRestController")
public class UserRestController extends CmiEmaController {

	/**
	 * Create a new User entity
	 * 
	 */
	@RequestMapping(value = "/newUser", method = RequestMethod.POST)
	@ResponseBody
	public Object newUser(@RequestBody User user) {
		userService.saveUser(user);
		return JSONObject.parse(cmiPsonService.toJsonString(userDAO.findUserByPrimaryKey(user.getId()), 2));
	}

	@RequestMapping(value = "/restNewUser", method = RequestMethod.POST)
	@ResponseBody
	public Object restNewUser(@RequestBody String userJson) {
		User user = new Gson().fromJson(userJson, User.class);
		appendReferences(user);
		userService.saveUser(user);
		return JSONObject.parse(cmiPsonService.toJsonString(userDAO.findUserByPrimaryKey(user.getId()), 2));
	}

	@RequestMapping(value = "/saveUser", method = RequestMethod.PUT)
	@ResponseBody
	public User saveUser(@RequestBody User user) {
		userService.saveUser(user);
		return userDAO.findUserByPrimaryKey(user.getId());
	}

	@RequestMapping(value = "/restSaveUser", method = RequestMethod.PUT)
	@ResponseBody
	public Object restSaveUser(@RequestBody String userJson) {
		User user = new Gson().fromJson(userJson, User.class);
		appendReferences(user);
		CmiPsonService cmiPsonService = new CmiPsonService();
		userService.saveUser(user);
		return JSONObject.parse(cmiPsonService.toJsonString(userDAO.findUserByPrimaryKey(user.getId()), 1));
	}

	@RequestMapping(value = "/restDeleteUser/{userId}", method = RequestMethod.DELETE)
	@ResponseBody
	public void restDeleteUser(@PathVariable Integer userId) {
		User user = userDAO.findUserByPrimaryKey(userId);
		userService.deleteUser(user);
	}

	@RequestMapping(value = "/restConfirmDeleteUsers")
	@ResponseBody
	public Object restConfirmDeleteUsers(@RequestBody Set<Integer> deleteUsersIds) {
		Set<User> deleteUsers = userDAO.findUsersByIds(deleteUsersIds);
		Set<User> referencedUsers = userService.loadReferenceUsers(deleteUsers);
		deleteUsers.removeAll(referencedUsers);
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("referencedEntitys", referencedUsers);
		jsonObject.put("deleteEntitys", deleteUsers);
		return JSONObject.parse(jsonObject.toJSONString());
	}

	@RequestMapping("/restDeleteUsers")
	@ResponseBody
	public Object restDeleteUsers(@RequestBody Set<User> deleteUsers) {
		Iterator<User> iterator = deleteUsers.iterator();
		while (iterator.hasNext()) {
			User currentUser = iterator.next();
			userService.deleteUser(currentUser);
		}
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("url", "listUsers");
		return JSONObject.parse(jsonObject.toJSONString());
	}
	// loadself

	@RequestMapping(value = "/restLoadUser/{userId}", method = RequestMethod.POST)
	@ResponseBody
	public Object restLoadUser(@PathVariable Integer userId, @RequestBody CmiPagination cmiPagination) {
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(cmiPsonService.toPsonString(userDAO.findUserByPrimaryKey(userId), 2, cmiPagination));
	}
	// loadReferenceds
	// TODO loadReferencedsPson，这个方法有一些问题，待修复

	@RequestMapping(value = "/restLoadUserDetects/{userId}/detects/{relateddetectId}", method = RequestMethod.POST)
	@ResponseBody
	public Object restLoadUserDetects(@PathVariable Integer userId, @PathVariable Integer relateddetectId,
			@RequestBody CmiPagination cmiPagination) {
		Detect detect = detectDAO.findDetectByPrimaryKey(relateddetectId, -1, -1);
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(cmiPsonService.toPsonString(detect, 2, cmiPagination));
	}

	@RequestMapping(value = "/restLoadUserEventsForAuditor/{userId}/eventsForAuditor/{relatedeventId}", method = RequestMethod.POST)
	@ResponseBody
	public Object restLoadUserEventsForAuditor(@PathVariable Integer userId, @PathVariable Integer relatedeventId,
			@RequestBody CmiPagination cmiPagination) {
		Event event = eventDAO.findEventByPrimaryKey(relatedeventId, -1, -1);
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(cmiPsonService.toPsonString(event, 2, cmiPagination));
	}

	@RequestMapping(value = "/restLoadUserEventsForReportor/{userId}/eventsForReportor/{relatedeventId}", method = RequestMethod.POST)
	@ResponseBody
	public Object restLoadUserEventsForReportor(@PathVariable Integer userId, @PathVariable Integer relatedeventId,
			@RequestBody CmiPagination cmiPagination) {
		Event event = eventDAO.findEventByPrimaryKey(relatedeventId, -1, -1);
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(cmiPsonService.toPsonString(event, 2, cmiPagination));
	}

	@RequestMapping(value = "/restLoadUserUrls/{userId}/urls/{relatedurlId}", method = RequestMethod.POST)
	@ResponseBody
	public Object restLoadUserUrls(@PathVariable Integer userId, @PathVariable Integer relatedurlId,
			@RequestBody CmiPagination cmiPagination) {
		Url url = urlDAO.findUrlByPrimaryKey(relatedurlId, -1, -1);
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(cmiPsonService.toPsonString(url, 2, cmiPagination));
	}

	@RequestMapping(value = "/restLoadUserAuthoritys/{userId}/authoritys/{relatedauthorityId}", method = RequestMethod.POST)
	@ResponseBody
	public Object restLoadUserAuthoritys(@PathVariable Integer userId, @PathVariable Integer relatedauthorityId,
			@RequestBody CmiPagination cmiPagination) {
		Authority authority = authorityDAO.findAuthorityByPrimaryKey(relatedauthorityId, -1, -1);
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(cmiPsonService.toPsonString(authority, 2, cmiPagination));
	}

	@RequestMapping(value = "/restLoadUserDetectdepartments/{userId}/detectdepartments/{relateddetectdepartmentId}", method = RequestMethod.POST)
	@ResponseBody
	public Object restLoadUserDetectdepartments(@PathVariable Integer userId,
			@PathVariable Integer relateddetectdepartmentId, @RequestBody CmiPagination cmiPagination) {
		Detectdepartment detectdepartment = detectdepartmentDAO
				.findDetectdepartmentByPrimaryKey(relateddetectdepartmentId, -1, -1);
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(cmiPsonService.toPsonString(detectdepartment, 2, cmiPagination));
	}

	public void appendReferences(User user) {

		// 引用表不是纯联系表，引用数量大于或者等于2
		Set<Detect> detectsForDetector = new HashSet<>();
		for (Detect detect_Detector : user.getDetectsForDetector()) {
			detectsForDetector.add(detectService.findDetectByPrimaryKey(detect_Detector.getId()));
		}
		user.setDetectsForDetector(detectsForDetector);

		// 引用表不是纯联系表，引用数量大于或者等于2
		Set<Event> eventsForAuditor = new HashSet<>();
		for (Event event_Auditor : user.getEventsForAuditor()) {
			eventsForAuditor.add(eventService.findEventByPrimaryKey(event_Auditor.getId()));
		}
		user.setEventsForAuditor(eventsForAuditor);

		// 引用表不是纯联系表，引用数量大于或者等于2
		Set<Event> eventsForReportor = new HashSet<>();
		for (Event event_Reportor : user.getEventsForReportor()) {
			eventsForReportor.add(eventService.findEventByPrimaryKey(event_Reportor.getId()));
		}
		user.setEventsForReportor(eventsForReportor);

		// 引用表不是纯联系表，引用数量大于或者等于2
		Set<Url> urlsForAuthor = new HashSet<>();
		for (Url url_Author : user.getUrlsForAuthor()) {
			urlsForAuthor.add(urlService.findUrlByPrimaryKey(url_Author.getId()));
		}
		user.setUrlsForAuthor(urlsForAuthor);

		// 引用表是纯联系表的情况
		Set<Authority> authoritysForUser = new HashSet<>();
		for (Authority authorityForUser : user.getAuthoritysForUser()) {
			authoritysForUser.add(authorityService.findAuthorityByPrimaryKey(authorityForUser.getId()));
		}
		user.setAuthoritysForUser(authoritysForUser);

		// 引用表是纯联系表的情况
		Set<Detectdepartment> detectdepartmentsForUser = new HashSet<>();
		for (Detectdepartment detectdepartmentForUser : user.getDetectdepartmentsForUser()) {
			detectdepartmentsForUser
					.add(detectdepartmentService.findDetectdepartmentByPrimaryKey(detectdepartmentForUser.getId()));
		}
		user.setDetectdepartmentsForUser(detectdepartmentsForUser);
	}

	@RequestMapping(value = "/restGetUserDetects/{userId}/detects", method = RequestMethod.POST)
	@ResponseBody
	public Object restGetUserDetects(@PathVariable Integer userId, @RequestBody CmiPagination cmiPagination) {
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(
				cmiPsonService.toPsonString(userDAO.findUserByPrimaryKey(userId).getDetectsForDetector(), 2, cmiPagination));
	}

	@RequestMapping(value = "/restGetUserEventsForAuditor/{userId}/eventsForAuditor", method = RequestMethod.POST)
	@ResponseBody
	public Object restGetUserEventsForAuditor(@PathVariable Integer userId, @RequestBody CmiPagination cmiPagination) {
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(
				cmiPsonService.toPsonString(userDAO.findUserByPrimaryKey(userId).getEventsForAuditor(), 2, cmiPagination));
	}

	@RequestMapping(value = "/restGetUserEventsForReportor/{userId}/eventsForReportor", method = RequestMethod.POST)
	@ResponseBody
	public Object restGetUserEventsForReportor(@PathVariable Integer userId, @RequestBody CmiPagination cmiPagination) {
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(
				cmiPsonService.toPsonString(userDAO.findUserByPrimaryKey(userId).getEventsForReportor(), 2, cmiPagination));
	}

	@RequestMapping(value = "/restGetUserUrls/{userId}/urls", method = RequestMethod.POST)
	@ResponseBody
	public Object restGetUserUrls(@PathVariable Integer userId, @RequestBody CmiPagination cmiPagination) {
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(
				cmiPsonService.toPsonString(userDAO.findUserByPrimaryKey(userId).getUrlsForAuthor(), 2, cmiPagination));
	}

	@RequestMapping(value = "/restGetUserAuthoritys/{userId}/authoritys", method = RequestMethod.POST)
	@ResponseBody
	public Object restGetUserAuthoritys(@PathVariable Integer userId, @RequestBody CmiPagination cmiPagination) {
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(
				cmiPsonService.toPsonString(userDAO.findUserByPrimaryKey(userId).getAuthoritysForUser(), 2, cmiPagination));
	}

	@RequestMapping(value = "/restGetUserDetectdepartments/{userId}/detectdepartments", method = RequestMethod.POST)
	@ResponseBody
	public Object restGetUserDetectdepartments(@PathVariable Integer userId, @RequestBody CmiPagination cmiPagination) {
		CmiPsonService cmiPsonService = new CmiPsonService();
		return JSONObject.parse(cmiPsonService
				.toPsonString(userDAO.findUserByPrimaryKey(userId).getDetectdepartmentsForUser(), 2, cmiPagination));
	}

	@RequestMapping(value = "/restListUsers", method = RequestMethod.GET)
	@ResponseBody
	public Object restListUsers() {
		return JSONObject.parse(cmiPsonService.toJsonString(userService.loadUsers(), 2));
	}

	@RequestMapping(value = "/restListUsersPost", method = RequestMethod.POST)
	@ResponseBody
	public Object restListUsersPost(@RequestBody CmiPagination cmiPagination) {

		CmiPsonService cmiPsonService = new CmiPsonService();
		cmiPagination = userPaginationService.updateAppPagination(cmiPagination);
		int startResult = (cmiPagination.getCurrentPagination() - 1) * cmiPagination.getPaginationSize();

		Set<User> users = userDAO.findAllUsers(startResult, cmiPagination.getPaginationSize());
		String userString = cmiPsonService.toPsonString(users, 2, cmiPagination);

		return JSONObject.parse(userString);
	}

	@RequestMapping("/userSelectBox")
	@ResponseBody
	public JSONObject userSelectBox(@RequestParam(required = false) String searchTable,
			@RequestParam(required = false) Set<Integer> searchValue, // 杨宏宇2019-9-10：searchValue是在selectpage.js的616行定义，如果要修改searchValue的名称，1.可以修改在selectpage.js修改；2.可以
																		// @RequestParam(value="searchValue", required =
																		// false) Set<Integer> someName
			@RequestParam(required = false, defaultValue = "10") int paginationSize,
			@RequestParam(required = false, defaultValue = "1") int pageNumber,
			@RequestParam(value = "qWord[]", required = false) String queryword,
			@RequestParam(required = false) String selectItem) throws IOException {
		Set entitySet = null;
		Integer count = 0;

		// 初始化原始值

		if (searchValue != null) {
			switch (searchTable) {
			// 外键

			// 被引用键
			case "Detect":
				entitySet = detectService.loadDetectsByIdSet(searchValue);
				break;
			case "Event":
				entitySet = eventService.loadEventsByIdSet(searchValue);
				break;
			case "Url":
				entitySet = urlService.loadUrlsByIdSet(searchValue);
				break;

			case "Authority":
				entitySet = authorityService.loadAuthoritysByIdSet(searchValue);
				break;

			case "Detectdepartment":
				entitySet = detectdepartmentService.loadDetectdepartmentsByIdSet(searchValue);
				break;
			}
			// 没有测试，深度需要多少？？？
			String jsonData = cmiPsonService.toJsonString(entitySet, 1);
			JSONArray jsonArray = new JSONArray();
			jsonArray = (JSONArray) JSON.parse((String) jsonData);

			JSONObject jsonObject = new JSONObject();
			jsonObject.put("list", jsonArray);
			jsonObject.put("totalRow", entitySet.size());
			return jsonObject;
		}

		// 不根据关键字进行搜索
		if (queryword == null || queryword.trim() == "") {
			switch (selectItem) {
			// 外键

			// 被引用键
			case "Detect":
				entitySet = detectDAO.findAllDetects((pageNumber - 1) * paginationSize, paginationSize);
				count = detectService.countDetects();
				break;
			case "Event":
				entitySet = eventDAO.findAllEvents((pageNumber - 1) * paginationSize, paginationSize);
				count = eventService.countEvents();
				break;
			case "Url":
				entitySet = urlDAO.findAllUrls((pageNumber - 1) * paginationSize, paginationSize);
				count = urlService.countUrls();
				break;

			case "Authority":
				entitySet = authorityDAO.findAllAuthoritys((pageNumber - 1) * paginationSize, paginationSize);
				count = authorityService.countAuthoritys();
				break;

			case "Detectdepartment":
				entitySet = detectdepartmentDAO.findAllDetectdepartments((pageNumber - 1) * paginationSize,
						paginationSize);
				count = detectdepartmentService.countDetectdepartments();
				break;
			}
		} else {
			switch (selectItem) {
			// 外键

			// 被引用键
			case "Detect":
				entitySet = detectDAO.findDetectByNameContaining(queryword, (pageNumber - 1) * paginationSize,
						paginationSize);
				count = detectService.countDetectsByName(queryword);
				break;
			case "Event":
				entitySet = eventDAO.findEventByNameContaining(queryword, (pageNumber - 1) * paginationSize,
						paginationSize);
				count = eventService.countEventsByName(queryword);
				break;
			case "Url":
				entitySet = urlDAO.findUrlByNameContaining(queryword, (pageNumber - 1) * paginationSize,
						paginationSize);
				count = urlService.countUrlsByName(queryword);
				break;

			case "Authority":
				entitySet = authorityDAO.findAuthorityByNameContaining(queryword, (pageNumber - 1) * paginationSize,
						paginationSize);
				count = authorityService.countAuthoritysByName(queryword);
				break;

			case "Detectdepartment":
				entitySet = detectdepartmentDAO.findDetectdepartmentByNameContaining(queryword,
						(pageNumber - 1) * paginationSize, paginationSize);
				count = detectdepartmentService.countDetectdepartmentsByName(queryword);
				break;
			}
		}
		/**
		 * 将Json数据转换成jsonArray形式，需要通过pson方式进行转换，然后再转换成JsonArray。因为存在懒加载
		 * 没有直接使用CmiPsonService中的fromJson方法是因为，fromJson方法会将int类型的直接转换成double类型的数据，这个问题还没有解决
		 */
		// 没有测试，深度需要多少？？？
		String jsonData = cmiPsonService.toJsonString(entitySet, 1);
		JSONArray jsonArray = new JSONArray();
		jsonArray = (JSONArray) JSON.parse((String) jsonData);

		JSONObject jsonObject = new JSONObject();
		jsonObject.put("list", jsonArray);
		jsonObject.put("paginationSize", paginationSize);
		jsonObject.put("pageNumber", pageNumber);
		jsonObject.put("totalRow", count);
		jsonObject.put("totalPaginations",
				count % paginationSize == 0 ? count / paginationSize : count / paginationSize + 1);
		return jsonObject;
	}
}
